package org.tool.spring.servlet;

import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.spring.SpringUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.tool.core.lang.StringUtil;
import org.tool.spring.servlet.support.InputStringManager;

import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;

/**
 * Servlet相关工具类
 *
 * @author 李坤
 * @date 2022/7/7 17:56
 */
public abstract class ServletUtil {

    /**
     * 请求响应内容的类型
     */
    private static final String CONTENT_TYPE = "application/json;charset=utf-8";

    /**
     * 特殊字符默认提示信息
     */
    public static final String SPECIAL_CHARACTERS_RESULT = "数据包含特殊字符[ {0} ]，请处理";

    /**
     * 获取当前请求对象
     *
     * @return {@link HttpServletRequest} 对象
     *
     * @see RequestContextHolder#getRequestAttributes()
     */
    public static HttpServletRequest servletRequest() {
        RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes();
        return (requestAttributes == null) ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
    }

    /**
     * 向前端回写数据
     *
     * @param data     回写的数据
     * @param response response
     *
     * @throws IOException IO异常
     */
    public static void write(Object data, HttpServletResponse response) throws IOException {
        response.setContentType(CONTENT_TYPE);

        try (PrintWriter writer = response.getWriter()) {
            writer.write(JSON.toJSONString(data));
            writer.flush();
        }
    }

    /**
     * 读取 HttpServletRequest 中的请求体数据
     *
     * @param request 请求
     *
     * @return 请求体
     *
     * @throws IOException IO异常
     */
    public static String getServletRequestBody(HttpServletRequest request) throws IOException {
        int index;
        try (ServletInputStream inputStream = request.getInputStream();
             ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
            byte[] bytes = new byte[1024];
            while ((index = inputStream.read(bytes)) > 0) {
                outputStream.write(bytes, 0, index);
            }
            return new String(outputStream.toByteArray(), StandardCharsets.UTF_8).intern();
        }
    }

    /**
     * 处理给定对象中的特殊字符串
     *
     * @param argument 给定的对象
     *
     * @return 处理后的数据
     */
    public static String processInputArgument(String uri, String argument) {
        if (SpringUtil.getBean(InputStringManager.class).enableProcessInputString() && StrUtil.isNotEmpty(argument)) {
            try {
                argument = processInputJson(uri, JSON.parseObject(argument));
            } catch (Exception exception) {
                try {
                    argument = processInputArray(uri, JSON.parseArray(argument));
                } catch (Exception e) {
                    argument = null;
                }
            }
            if ("\"".equals(argument) || "\\".equals(argument)) {
                argument = ("\\" + argument).intern();
            }
        }
        return argument;
    }


    /*----------------------------------------------private static class----------------------------------------------*/


    /**
     * 处理给定的 JSONObject 对象
     *
     * @param jsonObject 待处理的数据
     */
    private static String processInputJson(String uri, JSONObject jsonObject) {
        String specialCharacters = null;

        for (Map.Entry<String, Object> entry : jsonObject.entrySet()) {
            final String key = entry.getKey();
            final Object value = entry.getValue();

            if (value instanceof String) {
                String strValue = (String) value;
                if (StrUtil.isNotEmpty(strValue) && SpringUtil.getBean(InputStringManager.class).needProcess(uri, key)) {
                    specialCharacters = StringUtil.processInputString(strValue);
                }
            } else if (value instanceof JSONArray) {
                if (SpringUtil.getBean(InputStringManager.class).needProcess(uri, key)) {
                    specialCharacters = processInputArray(uri, (JSONArray) value);
                }
            } else if (value instanceof JSONObject) {
                if (SpringUtil.getBean(InputStringManager.class).needProcess(uri, key)) {
                    specialCharacters = processInputJson(uri, (JSONObject) value);
                }
            }

            if (StrUtil.isNotEmpty(specialCharacters)) {
                return specialCharacters;
            }
        }
        return specialCharacters;
    }

    /**
     * 处理给定的 JSONArray 对象
     *
     * @param jsonArray 待处理的数据
     */
    private static String processInputArray(String uri, JSONArray jsonArray) {
        String specialCharacters = null;

        for (final Object value : jsonArray) {
            if (value instanceof String) {
                String strValue = (String) value;
                if (StrUtil.isNotEmpty(strValue)) {
                    specialCharacters = StringUtil.processInputString(strValue);
                }
            } else if (value instanceof JSONArray) {
                specialCharacters = processInputArray(uri, (JSONArray) value);
            } else if (value instanceof JSONObject) {
                specialCharacters = processInputJson(uri, (JSONObject) value);
            }

            if (StrUtil.isNotEmpty(specialCharacters)) {
                return specialCharacters;
            }
        }
        return specialCharacters;
    }

}
